<?php
declare(strict_types=1);

namespace Vipkwd\Utils\Qrcode;

use Vipkwd\Utils\Libs\Qrcode\{QRtools, QRimage};

QRtools::markTime('start');
class QRimg extends QRimage
{
    //----------------------------------------------------------------------
    public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4, $saveandprint = FALSE, $back_color = 0xFFFFFF, $front_color = 0x000000, $style = false)
    {
        $image = self::image($frame, $pixelPerPoint, $outerFrame, $back_color, $front_color, $style);
        if ($filename === false) {
            Header("Content-type: image/png");
            ImagePng($image);
        } else {
            if ($saveandprint === true) {
                ImagePng($image, $filename);
                header("Content-type: image/png");
                ImagePng($image);
            } else {
                ImagePng($image, $filename);
            }
        }
        ImageDestroy($image);
    }

    //----------------------------------------------------------------------
    private static function image($frame, int $pixelPerPoint = 4, int $outerFrame = 4, $back_color = 0xFFFFFF, $front_color = 0x000000, $style = false)
    {

        $stylearray = ['plus', 'circle', '3d'];
        $style = in_array($style, $stylearray) ? $style : false;

        $dot = 1;
        if ($style) {
            $dot = $pixelPerPoint;
        }
        $outerFrame *= $dot;

        $h = count($frame);
        $w = strlen($frame[0]);

        $imgW = intval($w * $dot + $outerFrame * 2);
        $imgH = intval($h * $dot + $outerFrame * 2);

        $base_image = ImageCreate($imgW, $imgH);
        
        $back_color = QRtools::colorToHex($back_color);
        $front_color = QRtools::colorToHex($front_color);

        // convert a hexadecimal color code into decimal eps format (green = 0 1 0, blue = 0 0 1, ...)
        $r1 = intval(round(($front_color & 0xFF0000) >> 16, 5));
        $b1 = intval(round(($front_color & 0x00FF00) >> 8, 5));
        $g1 = intval(round($front_color & 0x0000FF, 5));

        // convert a hexadecimal color code into decimal eps format (green = 0 1 0, blue = 0 0 1, ...)
        $r2 = intval(round(($back_color & 0xFF0000) >> 16, 5));
        $b2 = intval(round(($back_color & 0x00FF00) >> 8, 5));
        $g2 = intval(round($back_color & 0x0000FF, 5));

        // Set a lighter color than the foreground
        $r1light = intval($r1 + (255 - $r1) / 2);
        $g1light = intval($g1 + (255 - $g1) / 2);
        $b1light = intval($b1 + (255 - $b1) / 2);

        $col[0] = ImageColorAllocate($base_image, $r2, $b2, $g2);
        $col[1] = ImageColorAllocate($base_image, $r1, $b1, $g1);
        $col[2] = ImageColorAllocate($base_image, $r1light, $g1light, $b1light);

        imagefill($base_image, 0, 0, $col[0]);

        $plusline = (int) min(max($dot / 8, 1), 8);
        $arrowline = (int) min(max($dot / 3, 1), 8);

        switch ($style) {
            case 'plus':
                for ($y = 0; $y < $h; $y++) {
                    for ($x = 0; $x < $w; $x++) {
                        if ($frame[$y][$x] == '1') {
                            // orizz line
                            $initx = intval($x * $dot + $outerFrame);
                            $endx = intval($x * $dot + $outerFrame + $dot);
                            $inity = intval($y * $dot + $outerFrame + $dot / 2 - $plusline);
                            $endy = intval($y * $dot + $outerFrame + $dot / 2 + $plusline);
                            imagefilledrectangle($base_image, $initx, $inity, $endx, $endy, $col[1]);
                            // vert line
                            $initx = intval($x * $dot + $outerFrame + $dot / 2 - $plusline);
                            $endx = intval($x * $dot + $outerFrame + $dot / 2 + $plusline);
                            $inity = intval($y * $dot + $outerFrame);
                            $endy = intval($y * $dot + $outerFrame + $dot);
                            imagefilledrectangle($base_image, $initx, $inity, $endx, $endy, $col[1]);
                        }
                    }
                }
                break;
            case 'circle':
                for ($y = 0; $y < $h; $y++) {
                    for ($x = 0; $x < $w; $x++) {
                        if ($frame[$y][$x] == '1') {
                            imagefilledellipse(
                                $base_image,
                                intval(($x * $dot - $dot / 2) + $outerFrame + $dot),
                                intval(($y * $dot - $dot / 2) + $outerFrame + $dot),
                                $dot,
                                $dot,
                                $col[1]
                            );
                        }
                    }
                }
                break;
            case '3d':
                for ($y = 0; $y < $h; $y++) {
                    for ($x = 0; $x < $w; $x++) {
                        if ($frame[$y][$x] == '1') {
                            /*
                            // PINI
                            $points = array(
                                $x*$dot+$outerFrame+($dot/2), $y*$dot+$outerFrame,
                                $x*$dot+$outerFrame, $y*$dot+$outerFrame+$dot,
                                $x*$dot+$outerFrame+$dot, $y*$dot+$outerFrame+$dot
                            );
                            imagefilledpolygon( $base_image, $points, 3, $col[1] );

                            // ARROW DOWN
                            $points = array(
                                $x*$dot+$outerFrame, $y*$dot+$outerFrame+($dot/2),
                                // $x*$dot+$outerFrame+$arrowline, $y*$dot+$outerFrame+($dot/2),
                                $x*$dot+$outerFrame+$arrowline, $y*$dot+$outerFrame,
                                $x*$dot+$outerFrame+$dot-$arrowline, $y*$dot+$outerFrame,
                                $x*$dot+$outerFrame+$dot-$arrowline, $y*$dot+$outerFrame+($dot/2),
                                $x*$dot+$outerFrame+$dot, $y*$dot+$outerFrame+($dot/2),
                                $x*$dot+$outerFrame+($dot/2), $y*$dot+$outerFrame+$dot,

                            );
                            imagefilledpolygon( $base_image, $points, 6, $col[1] );

                            // ARROW UP
                            $points = array(
                                $x*$dot+$outerFrame, $y*$dot+$outerFrame+($dot/2)+$arrowline,
                                $x*$dot+$outerFrame+$arrowline, $y*$dot+$outerFrame+($dot/2)+$arrowline,
                                $x*$dot+$outerFrame+$arrowline, $y*$dot+$outerFrame+$dot, // bottom
                                $x*$dot+$outerFrame+$dot-$arrowline, $y*$dot+$outerFrame+$dot, // bottom
                                $x*$dot+$outerFrame+$dot-$arrowline, $y*$dot+$outerFrame+($dot/2)+$arrowline,
                                $x*$dot+$outerFrame+$dot, $y*$dot+$outerFrame+($dot/2)+$arrowline,
                                $x*$dot+$outerFrame+($dot/2), $y*$dot+$outerFrame,

                            );
                            imagefilledpolygon( $base_image, $points, 7, $col[1] );
                            */

                            // TRIANGOLI 3d
                            $points = [
                                $x * $dot + $outerFrame + $dot,
                                $y * $dot + $outerFrame,
                                $x * $dot + $outerFrame,
                                $y * $dot + $outerFrame + $dot,
                                $x * $dot + $outerFrame + $dot,
                                $y * $dot + $outerFrame + $dot
                            ];
                            imagefilledpolygon($base_image, $points, 3, $col[2]);
                            // 3D
                            $points = [
                                $x * $dot + $outerFrame + $dot,
                                $y * $dot + $outerFrame, // Point 1 (x, y)
                                $x * $dot + $outerFrame,
                                $y * $dot + $outerFrame + $dot, // Point 2 (x, y)
                                $x * $dot + $outerFrame,
                                $y * $dot + $outerFrame // Point 3 (x, y)
                            ];
                            imagefilledpolygon($base_image, $points, 3, $col[1]);
                        }
                    }
                }
                break;

            default:
                for ($y = 0; $y < $h; $y++) {
                    for ($x = 0; $x < $w; $x++) {
                        if ($frame[$y][$x] == '1') {
                            ImageSetPixel(
                                $base_image,
                                intval($x + $outerFrame),
                                intval($y + $outerFrame),
                                intval($col[1])
                            );
                        }
                    }
                }
                break;
        }

        if (!$style) {
            $target_image = ImageCreate(intval($imgW * $pixelPerPoint), intval($imgH * $pixelPerPoint));
            ImageCopyResized(
                $target_image,
                $base_image,
                0,
                0,
                0,
                0,
                intval($imgW * $pixelPerPoint),
                intval($imgH * $pixelPerPoint),
                $imgW,
                $imgH
            );
        } else {
            $target_image = ImageCreate($imgW, $imgH);
            ImageCopyResized(
                $target_image,
                $base_image,
                0,
                0,
                0,
                0,
                $imgW,
                $imgH,
                $imgW,
                $imgH
            );
        }
        ImageDestroy($base_image);

        return $target_image;
    }

}
